﻿using AutoMapper.Internal;
using EasyDDD.Domain;
using EasyDDD.Infrastructure;
using EasyDDD.Infrastructure.EFCore.Records;
using EasyDDD.Infrastructure.EFCore.Repository;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Resources;
using System.Reflection;
using System.Threading.Tasks;

namespace EasyDDD.Application
{
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddDomainSevice<TMask>(this IServiceCollection services)
        {
            var assembly = typeof(TMask).Assembly;
            var types = assembly.GetTypes().Where(e => !e.IsGenericType && !e.IsAbstract && e.BaseType != null);
            var domainSevices = types.Where(e => typeof(IDomainSevice).IsAssignableFrom(e) || typeof(IDomainSevice<>).IsAssignableFrom(e));

            foreach (var item in domainSevices)
            {
                services.TryAddScoped(item);
            }

            return services;
        }

        public static IServiceCollection AddRepository<TContext>(this IServiceCollection services)
        {
            var types = typeof(TContext).Assembly.GetTypes().Where(e => !e.IsGenericType && !e.IsAbstract && e.BaseType != null && e.BaseType.IsGenericType);
            var repositories = types.Where(e => e.BaseType!.GetGenericTypeDefinition() == typeof(Repository<,,>) || e.BaseType.GetGenericTypeDefinition() == typeof(Repository<,>));
            foreach (var item in repositories)
            {
                services.TryAddScoped(item);
            }

            //TODO; 这个怎么注入 services.TryAddsScoped<IRepository<e, k>, item>();
            //foreach (var item in repositories)
            //{
            //    //foreach (IRepositoryAttribute attribute in item.GetCustomAttributes().Where(e => e.GetType() == typeof(IRepositoryAttribute)))
            //    //{
            //    //    //var k = attribute.TKey as IKey;
            //    //    //var e = attribute.TEntiy as IEntity<IKey>;


            //    //}

            //    //if (typeof(IRepository<SysMenu, SysMenuId>).IsAssignableFrom(item)) { 
                
            //    //}
            //}

            return services;
        }

        public static IServiceCollection AddRecords<TContext>(this IServiceCollection services)
        {
            var assembly = typeof(TContext).Assembly;
            var types = assembly.GetTypes().Where(e => !e.IsGenericType && !e.IsAbstract && e.BaseType != null && e.BaseType.IsGenericType);
            var queries = types.Where(e => e.BaseType!.GetGenericTypeDefinition() == typeof(Records<,>));

            foreach (var item in queries)
            {
                services.TryAddScoped(item);
            }

            return services;
        }

        public static IServiceCollection AddIntegrationEventHandler(this IServiceCollection services)
        {
            var assembly = Assembly.GetCallingAssembly();
            var types = assembly.GetTypes().Where(e => !e.IsGenericType && !e.IsAbstract && e.BaseType != null);
            var handlers = types.Where(e => typeof(IIntegrationEventHandler).IsAssignableFrom(e));

            foreach (var item in handlers)
            {
                services.TryAddTransient(item);
            }

            return services;
        }
    }
}
